package com.yinxin.wudasuanfa.sort;


import com.yinxin.util.ThreadUtil;

import java.util.Arrays;

/**
 * @author yinxin
 * @version 1.0
 * @Description: 堆排序
 * @date 2022/4/188:54
 */
public class HeapSort {
    /**
     * 堆排序入口
     *
     * @param arr 存储堆的数组
     */
    public static void heapSort(int[] arr) {
        // 建堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            heapify(arr, arr.length, i);
        }
        //排序
        for (int i = arr.length - 1; i > 0; i--) {
            //将排出来的大顶堆的堆顶和最后一个数置换
            swap(arr, i, 0);
            // i个元素，维护索引0也就是堆顶元素的性质
            heapify(arr, i, 0);
        }
    }

    /**
     * 维护堆的性质
     *
     * @param arr 存储堆的数组
     * @param n   维护堆的数组长度
     * @param i   维护节点的下标
     */
    public static void heapify(int[] arr, int n, int i) {
        int largest = i;
        int lson = i * 2 + 1;
        int rson = i * 2 + 2;
        if (lson < n && arr[largest] < arr[lson]) {//lson < n 和rson < n 保证不会去维护没有子节点的节点
            largest = lson;
        }
        if (rson < n && arr[largest] < arr[rson]) {
            largest = rson;
        }
        if (largest != i) {
            //如果最大节点索引改变了就需要交换数组中对应数据的位置(即将左节点或者右节点移动到根节点)
            swap(arr, i, largest);
            //递归调整大顶堆
            heapify(arr, n, largest);
        }
    }

    /**
     * 交换arr数组中索引i和索引j的存储位置
     *
     * @param arr
     * @param i
     * @param j
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{8, 5, 2, 12, 1, 13, 11};
        long start = System.currentTimeMillis();
        heapSort(arr);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
        System.out.println("最终的数组是：" + Arrays.toString(arr));
    }

}
